/**
 * 系统包含文件
 * 1. 操作系统/编译器 差异适配
 * 2. 公共宏定义
 */

#pragma once

#include <stdlib.h>
#include <stdint.h>
#include "std_err.h"

 // 仿真 IQ 数据类型
typedef enum {
	IQ_TYPE_NULL = 0,
	IQ_TYPE_INT16,
	IQ_TYPE_INT32,
	IQ_TYPE_FLOAT,
	IQ_TYPE_DOUBLE,
	IQ_TYPE_MAX,
} iq_type_t;

#define IQ_TYPE_SIZE_MAP {0, 2*sizeof(int16_t), 2*sizeof(int32_t), 2*sizeof(float), 2*sizeof(double), 0}

// ARB 文件头信息
typedef struct _arb_info {
    uint32_t nsamples;              ///< 采样点数量
    uint32_t bandwidth;             ///< 带宽, Hz
    uint32_t sample_rate;			///< 采样率, Hz
    double rms;                     ///< 均方根
    double par;                     ///< 峰均比
    //char name[64];
    //char time[64];
} arb_info_t;


#ifdef __cplusplus
extern "C" {
#endif

/**
* 获取指定类型的 IQ 每个数据点（含实部和虚部）对应的存储空间大小（字节数）
*/
int rf_iq_type_size(iq_type_t iq_type);

/**
* 根据 IQ 文件扩展名来判断 IQ 数据类型，支持的扩展名为:
*   .int16  => IQ_TYPE_INT16;
*   .int32  => IQ_TYPE_INT32;
*   .float  => IQ_TYPE_FLOAT;
*   .double => IQ_TYPE_DOUBLE;
*   .iqw    => IQ_TYPE_FLOAT;
* @return 如果无法识别，则返回 IQ_TYPE_NULL。
*/
iq_type_t rf_iq_filename_to_type(const char* fname_iq);

/**
* 获取当前已加载到缓存的仿真 IQ 数据类型(即实部和虚部的数据类型)
*/
iq_type_t rf_iqcache_get_iq_type();

/**
* 获取当前已加载到缓存的仿真 IQ 点数
*/
size_t rf_iqcache_get_iq_count();

/**
* 获取当前已加载到缓存的仿真 IQ 数据
*/
void* rf_iqcache_get_iq_data();

/**
* 转换并加载 NI IQ CSV 文件到缓存（iq_type 格式）做为仿真 IQ 使用
* @param fname_csv 要加载的 NI IQ CSV 文件名。
* @param iq_type 指定 IQ 数据类型
* @return 标准错误码
* @note CSV 文件格式约定: 数据前面有 "Sample Count,250000,250000" 表示数据格式为 "time,I,Q"; 数据前面有 "Sample Count,250000" 表示数据格式为 "I,Q"
*/
std_err_t rf_iqcache_load_ni_csv(const char *fname_csv, iq_type_t iq_type);

/**
* 加载指定格式的二进制 IQ 数据文件
* @param fname_iq 要加载的二进制 IQ 数据文件名。
* @param iq_type 指定 IQ 数据类型。如果为 IQ_TYPE_NULL 则根据文件扩展名自动判断 IQ 数据类型。支持的扩展名见 @see rf_iq_filename_to_type()
* @return 标准错误码
*/
std_err_t rf_iqcache_load(const char *fname_iq, iq_type_t iq_type);

/**
* 加载 ARB 文件
*/
std_err_t rf_iqcache_load_arb(const char *fname_arb, arb_info_t *arb_info);

/**
* 保存已加载到缓存的仿真 IQ 数据到指定格式的二进制 IQ 数据文件
* @fname_iq 指定二进制格式文件名
* @iq_type 指定 IQ 数据类型。如果 iq_type == SIMULATE_IQ_TYPE_NULL，则以文件扩展名自动判断格式。
* @return 标准错误码
*/
std_err_t rf_iqcache_save(const char *fname_iq, iq_type_t iq_type);

/**
* 清除已加载的 IQ 缓存
*/
void rf_iqcache_clear();


/**
* 下面这几个函数只加载 IQ 数据到缓冲区，但不做后续缓冲区内存管理，即与 rf_iqcache_xxx() 函数无关。
* @iqcache [out] 用于存放 IQ 数据缓冲区指针的指针。在加载时会根据文件中 IQ 数据量分配内存，加载的数据内存需由用户自行释放 !
* @iqcount [out] 用于存放 IQ 数据点数的指针。如果不为 NULL，则加载的数据内存需由用户自行释放。
* @return 标准错误码
*/
std_err_t rf_iqbuf_load_ni_csv(const char *fname_csv, iq_type_t iq_type, void **iqbuf, size_t *iqcount);
std_err_t rf_iqbuf_load(const char *fname_iq, iq_type_t iq_type, void **iqbuf, size_t *iqcount);
std_err_t rf_iqbuf_load_arb(const char *fname_arb, arb_info_t *arb_info, void **iqbuf, size_t *iqcount);

#ifdef __cplusplus
}
#endif
